/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package app.algo;

import java.awt.image.BufferedImage;
import java.util.ArrayList;

/**
 *
 * @author bharat
 */
public class ScaleSpaceExtremaDetector {

    public ArrayList<SiftFeature> detectExtremas(BufferedImage[][] DoG, int octaves, int intervals, double defaultKeyPointThreasold, int curvatureThreasold) {

        int count = 0;

        ArrayList<SiftFeature> keyPoints = new ArrayList<SiftFeature>(20);

        double primaryThreasold = 0.5 * defaultKeyPointThreasold / intervals ;
        float normalizedValue = 0.0f ;
        int o, i, row, column, width, height, imgBorder, pixVal;

        o = i = row = column = width = height = pixVal = 0;
        imgBorder = SiftSettings.SIFT_IMG_BORDER;

        System.out.println("Dog Octavs:" + DoG.length + ", Intervals: " + intervals);
        for (o = 0; o < octaves; o++) {
            for (i = 1; i <= intervals; i++) {

                width = DoG[o][0].getWidth();
                height = DoG[o][0].getHeight();

                for (row = imgBorder; row < width - imgBorder; row++) {
                    for (column = imgBorder; column < height - imgBorder; column++) {

                        try {

                            //System.out.println("Dog:" + DoG[o][i].getRGB(row, column));
                            /* Considerign only RGB values */
                            pixVal = DoG[o][i].getRGB(row, column);
                            normalizedValue =  ((1.0f) * pixVal) / Integer.MAX_VALUE ;

                            if (normalizedValue != 0){
                                count++ ;
                            }
                            /* perform preliminary check on contrast */
                            if ( Math.abs( normalizedValue) > primaryThreasold) {

                                /* Check for extrema in 3x3 grids in adjecent grids */
                                if (isExtremePoint(DoG, o, i, row, column)) {

                                   // System.out.println("Pix Vale : " + DoG[o][i].getRGB(row, column) + " , Abs Val: " + pixVal);
                                    /* This is a key feature point */
                                    /*
                                    feat = interp_extremum(dog_pyr, o, i, row, column, intvls, contr_thr);
                                    if (feat) {
                                    ddata = feat_detection_data(feat);
                                    if (!is_too_edge_like(dog_pyr[ddata ->  octv][ddata ->  intvl],
                                    ddata ->  row, ddata ->  column, curv_thr)) {
                                    cvSeqPush(features, feat);
                                    } else {
                                    free(ddata);
                                    }
                                    free(feat);
                                     * */
                                } /* End of extrema condition */
                            } /* End of primary thresold comparision*/
                        } catch (Exception e) {
                            System.out.println("Exception: Ocatav:" + o + ", Interval:" + i + ", row:" + row + ", col: " + column + ", Width:" + width + ", Height: " + height);
                            return null;
                        }
                    }   /* column loop */
                }       /* row loop */
            } /* interval loop */
        } /*ocatve  loop */

        System.out.println("Count = " + count);
        return keyPoints;
    }

    private boolean isExtremePoint(BufferedImage[][] DoG, int octave, int interval, int px, int py) {
        return checkForMaxima(DoG, octave, interval, px, py) || checkForMinima(DoG, octave, interval, px, py);
    }

    private boolean checkForMaxima(BufferedImage[][] DoG, int octave, int interval, int px, int py) {
        int pixVal = DoG[octave][interval].getRGB(px, py);

        /* check for maxima in 3x3 grid for adjecent octaves */
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                for (int k = -1; k <= 1; k++) {
                    try {
                        if (pixVal < DoG[octave][interval + i].getRGB(px + j, py + k)) {
                            return false;
                        }
                    } catch (Exception e) {
                        System.out.println("Exception thrown: interval:" + (interval + i) + ", X:" + (px + j) + ", Y:" + (py + k));
                        continue;
                    }
                }
            }
        }
        return true;
    }

    private boolean checkForMinima(BufferedImage[][] DoG, int octave, int interval, int px, int py) {
        int pixVal = DoG[octave][interval].getRGB(px, py);

        /* check for minima in 3x3 grid for adjecent octaves */
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                for (int k = -1; k <= 1; k++) {
                    try {
                        if (pixVal > DoG[octave][interval + i].getRGB(px + j, py + k)) {
                            return false;
                        }
                    } catch (Exception e) {
                        System.out.println("Exception thrown: interval:" + (interval + i) + ", X:" + (px + j) + ", Y:" + (py + k));
                        continue;
                    }
                }
            }
        }
        return true;
    }

    /*Calculates characteristic scale for each feature.*/
    public void calcFeatureScales(ArrayList<SiftFeature> keyPoints, double sigma, int intervals) {
        SiftFeature feat;
        FeatureData fData;
        double intvl;
        int i, n;

        n = keyPoints.size();
        for (i = 0; i < n; i++) {
            feat = keyPoints.get(i);
            fData = feat.featureData;
            intvl = fData.intvl + fData.subintvl;
            feat.scale = sigma * Math.pow(2.0, fData.octv + intvl / intervals);
            fData.scl_octv = sigma * Math.pow(2.0, intvl / intervals);
        }
    }
}
